package com.gvtv.main.quartz;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.gvtv.main.exception.ExecuteException;
import com.gvtv.main.execute.ExecuteJob;
import com.gvtv.main.execute.ExecuteJobManager;
import com.gvtv.main.job.JobInfo;
import com.gvtv.main.schedul.SchedulInfo;

@DisallowConcurrentExecution
public class QuartzExeJob implements Job {

	private static final Logger logger = Logger.getLogger(QuartzExeJob.class);
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		JobDetail jobDetail = context.getJobDetail();
		SchedulInfo schedulInfo = (SchedulInfo) jobDetail.getJobDataMap().get(QuartzService.EXE_SCHEDUL);
		List<ExecuteJob> executeJobs = null;
		try {
			executeJobs = this.getExecuteJobs(schedulInfo);
			if(executeJobs==null || executeJobs.isEmpty()){
				throw new ExecuteException(schedulInfo.getId()+" quartz调度中没有配置job，请检查。");
			}
			this.checkLegalDependJobs(executeJobs);
			logger.info(schedulInfo.getId() + " quartz 调度开始");
			ExecuteJobManager executeJobManager = new ExecuteJobManager(schedulInfo, executeJobs);
			executeJobManager.execute();
			logger.info(schedulInfo.getId() + " quartz 调度结束");
		} catch (ExecuteException e) {
			logger.error("检测到调度作业[" + schedulInfo.getId() + "#" + schedulInfo.getName() + "#]的作业存在问题 : "+e.getMessage());
		}
	}
	
	private List<ExecuteJob> getExecuteJobs(SchedulInfo schedulInfo) throws ExecuteException {
		if(schedulInfo.getJobs()==null){
			return null;
		}
		List<ExecuteJob> executeJobs = new ArrayList<ExecuteJob>();
		for (JobInfo jobInfo : schedulInfo.getJobs()) {
			ExecuteJob executeJob = new ExecuteJob(schedulInfo.getId(), jobInfo);
			executeJobs.add(executeJob);
		}
		this.createJobDepends(executeJobs);
		return executeJobs;
	}
	
	private void createJobDepends(List<ExecuteJob> executeJobs) throws ExecuteException {
		for (ExecuteJob executeJob : executeJobs) {
			if (StringUtils.isNotBlank(executeJob.getJobInfo().getRefJob())) {
				String[] refs = executeJob.getJobInfo().getRefJob().split(",");
				for (String id : refs) {
					if (!id.equals(executeJob.getId())) {
						ExecuteJob dependJob = this.getExecuteJob(id, executeJobs);
						if (dependJob != null) {
							executeJob.addDependJob(dependJob);
						} else {
							throw new ExecuteException("[" + executeJob.getId() + "] job 依赖的job [" + id + "] 不存在，请认真检查依赖job是否存在。");
						}
					} else {
						logger.warn("作业[" + executeJob.getId() + "]自己依赖自己，忽略该依赖关系。");
					}
				}
			}
		}
	}

	private ExecuteJob getExecuteJob(String id, List<ExecuteJob> executeJobs) {
		for (ExecuteJob executeJob : executeJobs) {
			if (id.equals(executeJob.getId())) {
				return executeJob;
			}
		}
		return null;
	}

	private void checkLegalDependJobs(List<ExecuteJob> executeJobs) throws ExecuteException {
		for (ExecuteJob executeJob : executeJobs) {
			findOwner(executeJob.getId(), executeJob.getDependJobs());
		}
	}

	private void findOwner(String jobId, List<ExecuteJob> dependJobs) throws ExecuteException {
		if (dependJobs == null) {
			return;
		}
		for (ExecuteJob executeJob : dependJobs) {
			if (executeJob.getId().equals(jobId)) {
				throw new ExecuteException("job之间存在死循环依赖，请检查!");
			} else if (executeJob.getDependJobs() != null) {
				findOwner(jobId, executeJob.getDependJobs());
			}
		}
	}
}
